#-*- coding:utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
#    d$
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import time
from datetime import date
from datetime import datetime
from datetime import timedelta
from dateutil import relativedelta

from openerp import netsvc
from openerp.osv import fields, osv
from openerp import tools
from openerp.tools.translate import _
import openerp.addons.decimal_precision as dp

from openerp.tools.safe_eval import safe_eval as eval

class hr_payslip(osv.osv):
    _inherit = 'hr.payslip'
    _description = 'Pay Slip'
    
    def onchange_employee_id(self, cr, uid, ids, date_from, date_to, employee_id=False, contract_id=False, context=None):
        empolyee_obj = self.pool.get('hr.employee')
        contract_obj = self.pool.get('hr.contract')
        worked_days_obj = self.pool.get('hr.payslip.worked_days')
        input_obj = self.pool.get('hr.payslip.input')

        if context is None:
            context = {}
        #delete old worked days lines
        old_worked_days_ids = ids and worked_days_obj.search(cr, uid, [('payslip_id', '=', ids[0])], context=context) or False
        if old_worked_days_ids:
            worked_days_obj.unlink(cr, uid, old_worked_days_ids, context=context)

        #delete old input lines
        old_input_ids = ids and input_obj.search(cr, uid, [('payslip_id', '=', ids[0])], context=context) or False
        if old_input_ids:
            input_obj.unlink(cr, uid, old_input_ids, context=context)


        #defaults
        res = {'value':{
                      'line_ids':[],
                      'input_line_ids': [],
                      'worked_days_line_ids': [],
                      #'details_by_salary_head':[], TODO put me back
                      'name':'',
                      'contract_id': False,
                      'struct_id': False,
                      }
            }
        if (not employee_id) or (not date_from) or (not date_to):
            return res
        ttyme = datetime.fromtimestamp(time.mktime(time.strptime(date_from, "%Y-%m-%d")))
        employee_id = empolyee_obj.browse(cr, uid, employee_id, context=context)
        res['value'].update({
                    'name': _('Pay Advice for the Month of %s ') % (tools.ustr(ttyme.strftime('%B-%Y'))),
                    'company_id': employee_id.company_id.id
        })

        if not context.get('contract', False):
            #fill with the first contract of the employee
            contract_ids = self.get_contract(cr, uid, employee_id, date_from, date_to, context=context)
        else:
            if contract_id:
                #set the list of contract for which the input have to be filled
                contract_ids = [contract_id]
            else:
                #if we don't give the contract, then the input to fill should be for all current contracts of the employee
                contract_ids = self.get_contract(cr, uid, employee_id, date_from, date_to, context=context)

        if not contract_ids:
            return res
        contract_record = contract_obj.browse(cr, uid, contract_ids[0], context=context)
        res['value'].update({
                    'contract_id': contract_record and contract_record.id or False
        })
        struct_record = contract_record and contract_record.struct_id or False
        if not struct_record:
            return res
        res['value'].update({
                    'struct_id': struct_record.id,
        })
        #computation of the salary input
        worked_days_line_ids = self.get_worked_day_lines(cr, uid, contract_ids, date_from, date_to, context=context)
        input_line_ids = self.get_inputs(cr, uid, contract_ids, date_from, date_to, context=context)
        res['value'].update({
                    'worked_days_line_ids': worked_days_line_ids,
                    'input_line_ids': input_line_ids,
        })
        return res
hr_payslip()
class hr_payslip_run(osv.osv):
    _inherit = 'hr.payslip.run'
    _columns = {
        'contract_type':fields.many2one('hr.contract.type','Contract Type', required=True, readonly=True, states={'draft': [('readonly', False)]}),
        'contract_ids': fields.many2many('hr.contract', 'arap_hr_payslip_run_rel', 'payslip_run_id', 'contract_id', 'Contracts', 
                                         required=True, domain="[('type_id','=',contract_type)]", readonly=True, states={'draft': [('readonly', False)]}),
    }
    _defaults = {
    }
    def generate_payslips(self, cr, uid, ids, context=None):
        slip_pool = self.pool.get('hr.payslip')
        if context is None:
            context = {}
        
        for run in self.browse(cr, uid, ids):
            slip_ids = []
            from_date =  run.date_start
            to_date = run.date_end
            credit_note = run.credit_note
            if not run.contract_ids:
                raise osv.except_osv(_("Warning!"), _("You must select contract(s) to generate payslip(s)."))
            for contract in run.contract_ids:
                payslip_ids = slip_pool.search(cr, uid, [('payslip_run_id','=',run.id),('contract_id','=',contract.id)])
                if not payslip_ids:
                    emp = contract.employee_id
                    slip_data = slip_pool.onchange_employee_id(cr, uid, [], from_date, to_date, emp.id, contract_id=contract.id, context=context)
                    res = {
                        'employee_id': emp.id,
                        'name': slip_data['value'].get('name', False),
                        'struct_id': slip_data['value'].get('struct_id', False),
                        'contract_id': contract.id,#slip_data['value'].get('contract_id', False),
                        'payslip_run_id': run.id,
                        'input_line_ids': [(0, 0, x) for x in slip_data['value'].get('input_line_ids', False)],
                        'worked_days_line_ids': [(0, 0, x) for x in slip_data['value'].get('worked_days_line_ids', False)],
                        'date_from': from_date,
                        'date_to': to_date,
                        'credit_note': credit_note,
                    }
                    slip_ids.append(slip_pool.create(cr, uid, res, context=context))
            
            if slip_ids:
                slip_pool.compute_sheet(cr, uid, slip_ids, context)
        return True
hr_payslip_run()